#pragma once

#include "room.hpp"

using room_ptr = std::shared_ptr<room>;

class room_manage
{
public:
    room_manage(users_table_ptr users_table, online_manager_ptr online_manager)
        : _next_rid(1)
        , _user_table(users_table)
        , _online_manager(online_manager)
    {
        LOG(DEBUG, "游戏房间管理已初始化完毕");
    }

    // 创建一个房间
    room_ptr create_room(uint32_t uid1, uint32_t uid2)
    {
        if (!_online_manager->in_game_hall(uid1))
        {
            LOG(WARNING, "%d 用户不在大厅中", uid1);
            return room_ptr();
        }
        if (!_online_manager->in_game_hall(uid2))
        {
            LOG(WARNING, "%d 用户不在大厅中", uid2);
            return room_ptr();
        }

        std::unique_lock<std::mutex> lock(_mutex);
        room_ptr rp(new gobang_room(_next_rid, _online_manager, _user_table));

        rp->addPlayer(uid1);
        rp->addPlayer(uid2);

        LOG(DEBUG, "uid1: %d, uid2: %d", uid1, uid2);

        _rooms.insert({_next_rid, rp}); // 房间ID 房间指针
        _users.insert({uid1, _next_rid});
        _users.insert({uid2, _next_rid});

        ++_next_rid;
        return rp;
    }


    room_ptr create_train_romm(uint32_t uid)
    {
        if (!_online_manager->in_game_hall(uid))
        {
            LOG(WARNING, "%d 用户不在大厅中", uid);
            return room_ptr();
        }

        std::unique_lock<std::mutex> lock(_mutex);
        room_ptr rp(new train_room(_next_rid, _online_manager, _user_table));
        rp->addPlayer(uid);

        _rooms.insert({_next_rid, rp}); // 房间ID 房间指针
        _users.insert({uid, _next_rid});
        ++_next_rid;
        return rp;
    }

    // 从房间id获取房间操作
    room_ptr get_room_from_rid(uint32_t rid)
    {
        std::unique_lock<std::mutex> lock(_mutex);
        auto it = _rooms.find(rid);
        if (it == _rooms.end())
        {
            return room_ptr(nullptr);
        }

        return it->second;
    }

    // 从uid获取房间操作
    room_ptr get_room_from_uid(uint32_t uid)
    {
        {
            std::unique_lock<std::mutex> lock(_mutex);
            if (_users.find(uid) == _users.end())
            {
                return room_ptr(nullptr);
            }
        }
        return get_room_from_rid(_users[uid]);
    }

    // 移除房间
    void erase_room(uint32_t rid)
    {
        room_ptr rp = get_room_from_rid(rid);
        if (rp.get() == nullptr)
            return;

        // uint32_t uid1 = rp->getWhitePlayer();
        // uint32_t uid2 = rp->getBlackPlayer();

        std::vector<uint32_t> users = rp->getAllPlayer();

        std::unique_lock<std::mutex> lock(_mutex);
        _users.erase(users[0]);
        _users.erase(users[1]);
        _rooms.erase(rid);
    }

    // 移除房间中的用户
    void erase_user_from_room(uint32_t uid)
    {
        room_ptr rp = get_room_from_uid(uid);
        if (rp.get() == nullptr)
            return;
        
        rp->handleExit(uid);

        // 如果玩家数为零，删除房间
        if (rp->player_count() == 0)
        {
            erase_room(rp->id());
        }
    }

private:
    uint32_t _next_rid;
    std::mutex _mutex;
    users_table_ptr _user_table;
    online_manager_ptr _online_manager;
    std::unordered_map<uint32_t, room_ptr> _rooms; // 房间ID与房间对应的操作
    std::unordered_map<uint32_t, uint32_t> _users; // 用户ID与房间ID关系
};